﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Issues.HeadmanNeedsGrainIssueBehavior
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using Helpers;
using System;
using System.Collections.Generic;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.Conversation;
using TaleWorlds.CampaignSystem.Extensions;
using TaleWorlds.CampaignSystem.MapEvents;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Roster;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using TaleWorlds.ObjectSystem;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Issues
{
  public class HeadmanNeedsGrainIssueBehavior : CampaignBehaviorBase
  {
    private const IssueBase.IssueFrequency HeadmanNeedsGrainIssueFrequency = IssueBase.IssueFrequency.Rare;
    private const int NearbyTownMarketGrainLimit = 100;
    private int _averageGrainPriceInCalradia;

    private static int AverageGrainPriceInCalradia
    {
      get
      {
        return Campaign.Current.GetCampaignBehavior<HeadmanNeedsGrainIssueBehavior>()._averageGrainPriceInCalradia;
      }
    }

    public override void RegisterEvents()
    {
      CampaignEvents.OnCheckForIssueEvent.AddNonSerializedListener((object) this, new Action<Hero>(this.OnCheckForIssue));
      CampaignEvents.WeeklyTickEvent.AddNonSerializedListener((object) this, new Action(this.WeeklyTick));
      CampaignEvents.OnGameLoadFinishedEvent.AddNonSerializedListener((object) this, new Action(this.OnGameLoadFinished));
      CampaignEvents.OnNewGameCreatedPartialFollowUpEvent.AddNonSerializedListener((object) this, new Action<CampaignGameStarter, int>(this.OnNewGameCreatedPartialFollowUp));
    }

    public override void SyncData(IDataStore dataStore)
    {
    }

    private bool ConditionsHold(Hero issueGiver)
    {
      return issueGiver.CurrentSettlement != null && issueGiver.IsNotable && issueGiver.CurrentSettlement.IsVillage && issueGiver.CurrentSettlement.Village.Bound.IsTown && issueGiver.IsHeadman && issueGiver.CurrentSettlement.Village.VillageType == DefaultVillageTypes.WheatFarm && (double) issueGiver.CurrentSettlement.Village.GetItemPrice(DefaultItems.Grain, (MobileParty) null, false) > (double) this._averageGrainPriceInCalradia * 1.2999999523162842;
    }

    public void OnCheckForIssue(Hero hero)
    {
      if (this.ConditionsHold(hero))
        Campaign.Current.IssueManager.AddPotentialIssueData(hero, new PotentialIssueData(new PotentialIssueData.StartIssueDelegate(this.OnSelected), typeof (HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssue), IssueBase.IssueFrequency.Rare));
      else
        Campaign.Current.IssueManager.AddPotentialIssueData(hero, new PotentialIssueData(typeof (HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssue), IssueBase.IssueFrequency.Rare));
    }

    private IssueBase OnSelected(in PotentialIssueData pid, Hero issueOwner)
    {
      return (IssueBase) new HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssue(issueOwner);
    }

    private void WeeklyTick() => this.CacheGrainPrice();

    private void OnGameLoadFinished() => this.CacheGrainPrice();

    private void OnNewGameCreatedPartialFollowUp(CampaignGameStarter starter, int i)
    {
      if (i != 99)
        return;
      this.CacheGrainPrice();
    }

    private void CacheGrainPrice()
    {
      this._averageGrainPriceInCalradia = QuestHelper.GetAveragePriceOfItemInTheWorld(DefaultItems.Grain);
    }

    public class HeadmanNeedsGrainIssue : IssueBase
    {
      private const int IssueDuration = 30;
      private const int AlternativeSolutionSuccessGenerosityBonus = 30;
      private const int AlternativeSolutionFailPowerPenalty = -5;
      private const int QuestTimeLimit = 18;
      private const int AlternativeSolutionSuccessPowerBonus = 10;
      private const int AlternativeSolutionSuccessRelationBonusWithQuestGiver = 2;
      private const int AlternativeSolutionSuccessRelationBonusWithOtherNotables = 1;
      private const int AlternativeSolutionFailRelationPenaltyWithNotables = -3;
      private const int AlternativeSolutionSuccessProsperityBonus = 50;
      private const int AlternativeSolutionFailProsperityPenalty = -10;
      private const int CompanionTradeSkillLimit = 120;
      [CachedData]
      private Settlement _nearbySuitableSettlementCache;

      internal static void AutoGeneratedStaticCollectObjectsHeadmanNeedsGrainIssue(
        object o,
        List<object> collectedObjects)
      {
        ((MBObjectBase) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        base.AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      public override IssueBase.AlternativeSolutionScaleFlag AlternativeSolutionScaleFlags
      {
        get => IssueBase.AlternativeSolutionScaleFlag.Duration;
      }

      private int NeededGrainAmount
      {
        get => (int) (12.0 + 180.0 * (double) this.IssueDifficultyMultiplier);
      }

      private int AlternativeSolutionNeededGold
      {
        get => this.NeededGrainAmount * HeadmanNeedsGrainIssueBehavior.AverageGrainPriceInCalradia;
      }

      public override int AlternativeSolutionBaseNeededMenCount
      {
        get => 3 + MathF.Ceiling(6f * this.IssueDifficultyMultiplier);
      }

      protected override int AlternativeSolutionBaseDurationInDaysInternal
      {
        get => 2 + MathF.Ceiling(6f * this.IssueDifficultyMultiplier);
      }

      protected override int RewardGold => 0;

      [CachedData]
      private Settlement NearbySuitableSettlement
      {
        get
        {
          if (this._nearbySuitableSettlementCache == null)
            this._nearbySuitableSettlementCache = SettlementHelper.FindNearestSettlement((Func<Settlement, bool>) (x =>
            {
              if (x.Town == null || x.Town.IsCastle || x.MapFaction.IsAtWarWith(this.IssueOwner.MapFaction))
                return false;
              int price = x.Town.MarketData.GetPrice(DefaultItems.Grain, MobileParty.MainParty);
              return price > 0 && price < HeadmanNeedsGrainIssueBehavior.AverageGrainPriceInCalradia * 2;
            }));
          return this._nearbySuitableSettlementCache;
        }
      }

      public override TextObject Title
      {
        get
        {
          TextObject title = new TextObject("{=sQBBOKDD}{ISSUE_SETTLEMENT} Needs Grain Seeds");
          title.SetTextVariable("ISSUE_SETTLEMENT", this.IssueSettlement.Name);
          return title;
        }
      }

      public override TextObject Description
      {
        get
        {
          TextObject description = new TextObject("{=OJObD61e}The headman of {ISSUE_SETTLEMENT} needs grain seeds for the coming sowing season.");
          description.SetTextVariable("ISSUE_SETTLEMENT", this.IssueSettlement.Name);
          return description;
        }
      }

      public override TextObject IssueBriefByIssueGiver
      {
        get
        {
          return new TextObject("{=p1buAbOQ}The harvest has been poor, and rats have eaten much of our stores. We can eat less and tighten our belts, but if we don't have seed grain left over to plant, we'll starve next year.[if:convo_dismayed][ib:demure2]");
        }
      }

      public override TextObject IssueAcceptByPlayer
      {
        get => new TextObject("{=vKwndBbe}Is there a way to prevent this?");
      }

      public override TextObject IssueQuestSolutionExplanationByIssueGiver
      {
        get
        {
          TextObject explanationByIssueGiver = new TextObject("{=nG750jQB}Grain will solve our problems. If we had {GRAIN_AMOUNT} bushels, we could use it to sow our fields. But I doubt that {NEARBY_TOWN} has so much to sell at this time of the year. {GRAIN_AMOUNT} bushels of grain costs around {DENAR_AMOUNT}{GOLD_ICON} in the markets, and we don't have that![if:convo_thinking]");
          int price = this.NearbySuitableSettlement.Town.MarketData.GetPrice(DefaultItems.Grain, MobileParty.MainParty);
          explanationByIssueGiver.SetTextVariable("NEARBY_TOWN", this.NearbySuitableSettlement.Name);
          explanationByIssueGiver.SetTextVariable("GRAIN_AMOUNT", this.NeededGrainAmount);
          explanationByIssueGiver.SetTextVariable("DENAR_AMOUNT", price * this.NeededGrainAmount);
          explanationByIssueGiver.SetTextVariable("GOLD_ICON", "{=!}<img src=\"General\\Icons\\Coin@2x\" extend=\"8\">");
          return explanationByIssueGiver;
        }
      }

      public override TextObject IssueAlternativeSolutionExplanationByIssueGiver
      {
        get
        {
          TextObject to = new TextObject("{=5NYPqKBj}I know you're busy, but maybe you can ask some of your men to find us that grain? {MEN_COUNT} men should do the job along with {GOLD}{GOLD_ICON}, and I'd reckon the whole affair should take two weeks. \nI'm desperate here, {?PLAYER.GENDER}madam{?}sir{\\?}... Don't let our children starve![if:convo_dismayed][ib:demure]");
          to.SetTextVariable("MEN_COUNT", this.GetTotalAlternativeSolutionNeededMenCount());
          to.SetTextVariable("GOLD", this.AlternativeSolutionNeededGold);
          to.SetTextVariable("GOLD_ICON", "{=!}<img src=\"General\\Icons\\Coin@2x\" extend=\"8\">");
          to.SetCharacterProperties("PLAYER", Hero.MainHero.CharacterObject);
          return to;
        }
      }

      public override TextObject IssueQuestSolutionAcceptByPlayer
      {
        get => new TextObject("{=ihfuqu2S}I will find that seed grain for you.");
      }

      public override TextObject IssueAlternativeSolutionAcceptByPlayer
      {
        get
        {
          TextObject solutionAcceptByPlayer = new TextObject("{=HCMsvAFv}I can order one of my companions and {MEN_COUNT} men to find grain for you.");
          solutionAcceptByPlayer.SetTextVariable("MEN_COUNT", this.GetTotalAlternativeSolutionNeededMenCount());
          return solutionAcceptByPlayer;
        }
      }

      public override TextObject IssueDiscussAlternativeSolution
      {
        get
        {
          return new TextObject("{=W6X5DffB}Thank you for sparing the men to bring us that seed grain, {?PLAYER.GENDER}madam{?}sir{\\?}. That should get us through the hard times ahead.[if:convo_grateful][ib:normal]");
        }
      }

      public override TextObject IssueAsRumorInSettlement
      {
        get
        {
          TextObject parent = new TextObject("{=WVobv24n}Heaven save us if {QUEST_GIVER.NAME} can't get {?QUEST_GIVER.GENDER}her{?}his{\\?} hands on more grain.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.IssueOwner.CharacterObject, parent);
          return parent;
        }
      }

      public override TextObject IssueAlternativeSolutionResponseByIssueGiver
      {
        get
        {
          return new TextObject("{=k63ZKmXX}Thank you, {?PLAYER.GENDER}milady{?}sir{\\?}! You are a saviour.[if:convo_grateful][ib:normal]");
        }
      }

      public override bool IsThereAlternativeSolution => true;

      public override bool IsThereLordSolution => false;

      protected override TextObject AlternativeSolutionStartLog
      {
        get
        {
          TextObject parent = new TextObject("{=a0UTO8tW}{ISSUE_OWNER.LINK}, the headman of {ISSUE_SETTLEMENT}, asked you to deliver {GRAIN_AMOUNT} bushels of grain to {?QUEST_GIVER.GENDER}her{?}him{\\?} to use as seeds. Otherwise the peasants cannot sow their fields and starve in the coming season. You have agreed to send your companion {COMPANION.NAME} along with {MEN_COUNT} men to find some grain and return to the village. Your men should return in {RETURN_DAYS} days.");
          StringHelpers.SetCharacterProperties("ISSUE_OWNER", this.IssueOwner.CharacterObject, parent);
          StringHelpers.SetCharacterProperties("COMPANION", this.AlternativeSolutionHero.CharacterObject, parent);
          parent.SetTextVariable("ISSUE_SETTLEMENT", this.IssueSettlement.Name);
          parent.SetTextVariable("GRAIN_AMOUNT", this.NeededGrainAmount);
          parent.SetTextVariable("RETURN_DAYS", this.GetTotalAlternativeSolutionDurationInDays());
          parent.SetTextVariable("MEN_COUNT", this.AlternativeSolutionSentTroops.TotalManCount - 1);
          return parent;
        }
      }

      protected override int CompanionSkillRewardXP
      {
        get => (int) (500.0 + 700.0 * (double) this.IssueDifficultyMultiplier);
      }

      public HeadmanNeedsGrainIssue(Hero issueOwner)
        : base(issueOwner, CampaignTime.DaysFromNow(30f))
      {
      }

      protected override float GetIssueEffectAmountInternal(IssueEffect issueEffect)
      {
        if (issueEffect == DefaultIssueEffects.SettlementProsperity)
          return -0.2f;
        return issueEffect == DefaultIssueEffects.SettlementLoyalty ? -0.5f : 0.0f;
      }

      public override (SkillObject, int) GetAlternativeSolutionSkill(Hero hero)
      {
        return (hero.GetSkillValue(DefaultSkills.Trade) >= hero.GetSkillValue(DefaultSkills.Medicine) ? DefaultSkills.Trade : DefaultSkills.Medicine, 120);
      }

      public override bool DoTroopsSatisfyAlternativeSolution(
        TroopRoster troopRoster,
        out TextObject explanation)
      {
        explanation = TextObject.Empty;
        return QuestHelper.CheckRosterForAlternativeSolution(troopRoster, this.GetTotalAlternativeSolutionNeededMenCount(), ref explanation);
      }

      public override bool AlternativeSolutionCondition(out TextObject explanation)
      {
        explanation = TextObject.Empty;
        return QuestHelper.CheckRosterForAlternativeSolution(MobileParty.MainParty.MemberRoster, this.GetTotalAlternativeSolutionNeededMenCount(), ref explanation) && QuestHelper.CheckGoldForAlternativeSolution(this.AlternativeSolutionNeededGold, ref explanation);
      }

      public override void AlternativeSolutionStartConsequence()
      {
        GiveGoldAction.ApplyForCharacterToParty(Hero.MainHero, this.IssueSettlement.Party, this.AlternativeSolutionNeededGold);
        TextObject textObject = new TextObject("{=ex6ZhAAv}You gave {DENAR}{GOLD_ICON} to companion to buy {GRAIN_AMOUNT} units of grain for the {ISSUE_OWNER.NAME}.");
        textObject.SetTextVariable("GRAIN_AMOUNT", this.NeededGrainAmount);
        textObject.SetTextVariable("DENAR", this.AlternativeSolutionNeededGold);
        textObject.SetTextVariable("GOLD_ICON", "{=!}<img src=\"General\\Icons\\Coin@2x\" extend=\"8\">");
        StringHelpers.SetCharacterProperties("ISSUE_OWNER", this.IssueOwner.CharacterObject, textObject);
        MBInformationManager.AddQuickInformation(textObject);
      }

      protected override void AlternativeSolutionEndWithSuccessConsequence()
      {
        TraitLevelingHelper.OnIssueSolvedThroughAlternativeSolution(this.IssueOwner, new Tuple<TraitObject, int>[1]
        {
          new Tuple<TraitObject, int>(DefaultTraits.Generosity, 30)
        });
        this.IssueOwner.AddPower(10f);
        this.IssueSettlement.Village.Bound.Town.Prosperity += 50f;
        this.RelationshipChangeWithIssueOwner = 2;
        foreach (Hero notable in (List<Hero>) this.IssueOwner.CurrentSettlement.Notables)
        {
          if (notable != this.IssueOwner)
            ChangeRelationAction.ApplyPlayerRelation(notable, 1);
        }
      }

      protected override void AlternativeSolutionEndWithFailureConsequence()
      {
        this.IssueOwner.AddPower(-5f);
        foreach (Hero notable in (List<Hero>) this.IssueOwner.CurrentSettlement.Notables)
          ChangeRelationAction.ApplyPlayerRelation(notable, -3);
        this.IssueSettlement.Village.Bound.Town.Prosperity += -10f;
      }

      public override IssueBase.IssueFrequency GetFrequency() => IssueBase.IssueFrequency.Rare;

      public override bool IssueStayAliveConditions()
      {
        return this.NearbySuitableSettlement != null && this.NearbySuitableSettlement.Town.MarketData.GetItemCountOfCategory(DefaultItems.Grain.ItemCategory) < 100;
      }

      protected override void CompleteIssueWithTimedOutConsequences()
      {
      }

      protected override void OnGameLoad()
      {
      }

      protected override void HourlyTick()
      {
      }

      protected override QuestBase GenerateIssueQuest(string questId)
      {
        return (QuestBase) new HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest(questId, this.IssueOwner, CampaignTime.DaysFromNow(18f), this.IssueDifficultyMultiplier, this.RewardGold, this.NeededGrainAmount);
      }

      protected override bool CanPlayerTakeQuestConditions(
        Hero issueGiver,
        out IssueBase.PreconditionFlags flag,
        out Hero relationHero,
        out SkillObject skill)
      {
        skill = (SkillObject) null;
        relationHero = (Hero) null;
        flag = IssueBase.PreconditionFlags.None;
        if ((double) issueGiver.GetRelationWithPlayer() < -10.0)
        {
          flag |= IssueBase.PreconditionFlags.Relation;
          relationHero = issueGiver;
        }
        if (FactionManager.IsAtWarAgainstFaction(issueGiver.CurrentSettlement.MapFaction, Hero.MainHero.MapFaction))
          flag |= IssueBase.PreconditionFlags.AtWar;
        return flag == IssueBase.PreconditionFlags.None;
      }
    }

    public class HeadmanNeedsGrainIssueQuest : QuestBase
    {
      private const int SuccessMercyBonus = 70;
      private const int SuccessGenerosityBonus = 50;
      private const int SuccessRelationBonusWithQuestGiver = 2;
      private const int SuccessRelationBonusWithOtherNotables = 1;
      private const int SuccessPowerBonus = 10;
      private const int SuccessProsperityBonus = 50;
      private const int FailRelationPenalty = -5;
      private const int FailRelationPenaltyWithOtherNotables = -3;
      private const int CrimeRatingFailHonorPenalty = -50;
      private const int CrimeRatingFailRelationshipWithQuestGiverPenalty = -5;
      private const int CrimeRatingFailQuestGiverPowerPenalty = -10;
      private const int TimeOutProsperityPenalty = -10;
      private const int TimeOutPowerPenalty = -5;
      [SaveableField(10)]
      private readonly int _neededGrainAmount;
      [SaveableField(20)]
      private int _rewardGold;
      [SaveableField(30)]
      private JournalLog _playerAcceptedQuestLog;
      [SaveableField(40)]
      private JournalLog _playerHasNeededGrainsLog;

      internal static void AutoGeneratedStaticCollectObjectsHeadmanNeedsGrainIssueQuest(
        object o,
        List<object> collectedObjects)
      {
        ((MBObjectBase) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        base.AutoGeneratedInstanceCollectObjects(collectedObjects);
        collectedObjects.Add((object) this._playerAcceptedQuestLog);
        collectedObjects.Add((object) this._playerHasNeededGrainsLog);
      }

      internal static object AutoGeneratedGetMemberValue_neededGrainAmount(object o)
      {
        return (object) ((HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest) o)._neededGrainAmount;
      }

      internal static object AutoGeneratedGetMemberValue_rewardGold(object o)
      {
        return (object) ((HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest) o)._rewardGold;
      }

      internal static object AutoGeneratedGetMemberValue_playerAcceptedQuestLog(object o)
      {
        return (object) ((HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest) o)._playerAcceptedQuestLog;
      }

      internal static object AutoGeneratedGetMemberValue_playerHasNeededGrainsLog(object o)
      {
        return (object) ((HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest) o)._playerHasNeededGrainsLog;
      }

      public override TextObject Title
      {
        get
        {
          TextObject title = new TextObject("{=apr2dH0n}{ISSUE_SETTLEMENT} Needs Grain Seeds");
          title.SetTextVariable("ISSUE_SETTLEMENT", this.QuestGiver.CurrentSettlement.Name);
          return title;
        }
      }

      public override bool IsRemainingTimeHidden => false;

      private TextObject _playerAcceptedQuestLogText
      {
        get
        {
          TextObject parent = new TextObject("{=5CokRxmL}{QUEST_GIVER.LINK}, the headman of the {QUEST_SETTLEMENT} asked you to deliver {GRAIN_AMOUNT} units of grain to {?QUEST_GIVER.GENDER}her{?}him{\\?} to use as seeds. Otherwise peasants cannot sow their fields and starve in the coming season. \n \n You have agreed to bring them {GRAIN_AMOUNT} units of grain as soon as possible.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          parent.SetTextVariable("QUEST_SETTLEMENT", this.QuestGiver.CurrentSettlement.Name);
          parent.SetTextVariable("GRAIN_AMOUNT", this._neededGrainAmount);
          return parent;
        }
      }

      private TextObject _playerHasNeededGrainsLogText
      {
        get
        {
          TextObject neededGrainsLogText = new TextObject("{=vOHc5dxC}You now have enough grain seeds to complete the quest. Return to {QUEST_SETTLEMENT} to hand them over.");
          neededGrainsLogText.SetTextVariable("QUEST_SETTLEMENT", this.QuestGiver.CurrentSettlement.Name);
          return neededGrainsLogText;
        }
      }

      private TextObject _questTimeoutLogText
      {
        get
        {
          TextObject questTimeoutLogText = new TextObject("{=brDw7ewN}You have failed to deliver {GRAIN_AMOUNT} units of grain to the villagers. They won't be able to sow them before the coming winter. The Headman and the villagers are doomed.");
          questTimeoutLogText.SetTextVariable("GRAIN_AMOUNT", this._neededGrainAmount);
          return questTimeoutLogText;
        }
      }

      private TextObject _successLog
      {
        get
        {
          TextObject successLog = new TextObject("{=GGTxzAtn}You have delivered {GRAIN_AMOUNT} units of grain to the villagers. They will be able to sow them before the coming winter. You have saved a lot of lives today. The Headman and the villagers are grateful.");
          successLog.SetTextVariable("GRAIN_AMOUNT", this._neededGrainAmount);
          return successLog;
        }
      }

      private TextObject _cancelLogOnWarDeclared
      {
        get
        {
          TextObject parent = new TextObject("{=8Z4vlcib}Your clan is now at war with the {ISSUE_GIVER.LINK}'s lord. Your agreement with {ISSUE_GIVER.LINK} was canceled.");
          StringHelpers.SetCharacterProperties("ISSUE_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _failLogOnWarDeclaredByCriminalRating
      {
        get
        {
          TextObject to = new TextObject("{=BTp7qpak}You are accused of a crime, and {QUEST_GIVER.LINK} no longer wants your help.");
          to.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject);
          return to;
        }
      }

      private TextObject _playerDeclaredWarQuestLogText
      {
        get
        {
          TextObject parent = new TextObject("{=bqeWVVEE}Your actions have started a war with {QUEST_GIVER.LINK}'s faction. {?QUEST_GIVER.GENDER}She{?}He{\\?} cancels your agreement and the quest is a failure.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _cancelLogOnVillageRaided
      {
        get
        {
          TextObject parent = new TextObject("{=PgFJLK85}{SETTLEMENT_NAME} is raided. It isn’t safe for the villagers to plant their fields, and agreement with {ISSUE_GIVER.LINK} was canceled.");
          parent.SetTextVariable("SETTLEMENT_NAME", this.QuestGiver.CurrentSettlement.Name);
          StringHelpers.SetCharacterProperties("ISSUE_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      public HeadmanNeedsGrainIssueQuest(
        string questId,
        Hero giverHero,
        CampaignTime duration,
        float difficultyMultiplier,
        int rewardGold,
        int neededGrainAmount)
        : base(questId, giverHero, duration, rewardGold)
      {
        this._neededGrainAmount = neededGrainAmount;
        this._rewardGold = rewardGold;
        this.SetDialogs();
        this.InitializeQuestOnCreation();
      }

      protected override void InitializeQuestOnGameLoad() => this.SetDialogs();

      protected override void HourlyTick()
      {
      }

      protected override void RegisterEvents()
      {
        CampaignEvents.PlayerInventoryExchangeEvent.AddNonSerializedListener((object) this, new Action<List<(ItemRosterElement, int)>, List<(ItemRosterElement, int)>, bool>(this.OnPlayerInventoryExchange));
        CampaignEvents.OnPartyConsumedFoodEvent.AddNonSerializedListener((object) this, new Action<MobileParty>(this.OnPartyConsumedFood));
        CampaignEvents.OnHeroSharedFoodWithAnotherHeroEvent.AddNonSerializedListener((object) this, new Action<Hero, Hero, float>(this.OnHeroSharedFoodWithAnotherHero));
        CampaignEvents.WarDeclared.AddNonSerializedListener((object) this, new Action<IFaction, IFaction, DeclareWarAction.DeclareWarDetail>(this.OnWarDeclared));
        CampaignEvents.OnClanChangedKingdomEvent.AddNonSerializedListener((object) this, new Action<Clan, Kingdom, Kingdom, ChangeKingdomAction.ChangeKingdomActionDetail, bool>(this.OnClanChangedKingdom));
        CampaignEvents.MapEventStarted.AddNonSerializedListener((object) this, new Action<MapEvent, PartyBase, PartyBase>(this.OnMapEventStarted));
        CampaignEvents.HourlyTickPartyEvent.AddNonSerializedListener((object) this, new Action<MobileParty>(this.HourlyTickParty));
        CampaignEvents.HeroPrisonerTaken.AddNonSerializedListener((object) this, new Action<PartyBase, Hero>(this.OnHeroPrisonerTaken));
        CampaignEvents.SettlementEntered.AddNonSerializedListener((object) this, new Action<MobileParty, Settlement, Hero>(this.OnSettlementEntered));
        CampaignEvents.VillageBeingRaided.AddNonSerializedListener((object) this, new Action<Village>(this.OnVillageBeingRaided));
      }

      private void OnMapEventStarted(
        MapEvent mapEvent,
        PartyBase attackerParty,
        PartyBase defenderParty)
      {
        if (QuestHelper.CheckMinorMajorCoercion((QuestBase) this, mapEvent, attackerParty))
        {
          QuestHelper.ApplyGenericMinorMajorCoercionConsequences((QuestBase) this, mapEvent);
        }
        else
        {
          if (!mapEvent.IsRaid && !mapEvent.IsForcingSupplies && !mapEvent.IsForcingVolunteers)
            return;
          this.CompleteQuestWithCancel(this._cancelLogOnVillageRaided);
        }
      }

      private void HourlyTickParty(MobileParty mobileParty)
      {
        if (mobileParty != MobileParty.MainParty)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnHeroPrisonerTaken(PartyBase capturer, Hero prisoner)
      {
        if (prisoner != Hero.MainHero)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnSettlementEntered(MobileParty party, Settlement settlement, Hero hero)
      {
        if (party != MobileParty.MainParty)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnVillageBeingRaided(Village village)
      {
        if (village != this.QuestGiver.CurrentSettlement.Village)
          return;
        this.CompleteQuestWithCancel(this._cancelLogOnVillageRaided);
      }

      protected override void OnTimedOut()
      {
        this.AddLog(this._questTimeoutLogText);
        this.TimeoutFail();
      }

      protected override void SetDialogs()
      {
        TextObject textObject1 = new TextObject("{=nwIYsJRO}Have you brought our grain {?PLAYER.GENDER}milady{?}sir{\\?}?[if:convo_shocked][ib:demure2]");
        TextObject textObject2 = new TextObject("{=zsE7ldPY}Thank you, {?PLAYER.GENDER}milady{?}sir{\\?}! You are a saviour.[if:convo_merry][ib:normal2]");
        TextObject textObject3 = new TextObject("{=0tB3VGE4}We await your success, {?PLAYER.GENDER}milady{?}sir{\\?}.[if:convo_nervous]");
        textObject1.SetCharacterProperties("PLAYER", Hero.MainHero.CharacterObject);
        textObject2.SetCharacterProperties("PLAYER", Hero.MainHero.CharacterObject);
        textObject3.SetCharacterProperties("PLAYER", Hero.MainHero.CharacterObject);
        this.OfferDialogFlow = DialogFlow.CreateDialogFlow("issue_classic_quest_start").NpcLine(textObject2).Condition((ConversationSentence.OnConditionDelegate) (() => CharacterObject.OneToOneConversationCharacter == this.QuestGiver.CharacterObject)).Consequence(new ConversationSentence.OnConsequenceDelegate(this.QuestAcceptedConsequences)).CloseDialog();
        this.DiscussDialogFlow = DialogFlow.CreateDialogFlow("quest_discuss").NpcLine(textObject1).Condition((ConversationSentence.OnConditionDelegate) (() =>
        {
          MBTextManager.SetTextVariable("GRAIN_AMOUNT", this._neededGrainAmount);
          return CharacterObject.OneToOneConversationCharacter == this.QuestGiver.CharacterObject;
        })).BeginPlayerOptions().PlayerOption(new TextObject("{=9UABeRWO}Yes. Here is your grain.")).ClickableCondition(new ConversationSentence.OnClickableConditionDelegate(this.CompleteQuestClickableConditions)).NpcLine(textObject2).Consequence((ConversationSentence.OnConsequenceDelegate) (() => Campaign.Current.ConversationManager.ConversationEndOneShot += new Action(this.Success))).CloseDialog().PlayerOption(new TextObject("{=PI6ikMsc}I'm working on it.")).NpcLine(textObject3).CloseDialog().EndPlayerOptions().CloseDialog();
      }

      private bool CompleteQuestClickableConditions(out TextObject explanation)
      {
        if (this._playerAcceptedQuestLog.CurrentProgress >= this._neededGrainAmount)
        {
          explanation = TextObject.Empty;
          return true;
        }
        explanation = new TextObject("{=mzabdwoh}You don't have enough grain.");
        return false;
      }

      private void QuestAcceptedConsequences()
      {
        this.StartQuest();
        this._playerAcceptedQuestLog = this.AddDiscreteLog(this._playerAcceptedQuestLogText, new TextObject("{=eEwI880g}Collect Grain"), this.GetRequiredGrainCountOnPlayer(), this._neededGrainAmount);
      }

      private int GetRequiredGrainCountOnPlayer()
      {
        int itemNumber = PartyBase.MainParty.ItemRoster.GetItemNumber(DefaultItems.Grain);
        if (itemNumber >= this._neededGrainAmount)
        {
          TextObject message = new TextObject("{=Gtbfm10o}You have enough grain to complete the quest. Return to {QUEST_SETTLEMENT} to hand it over.");
          message.SetTextVariable("QUEST_SETTLEMENT", this.QuestGiver.CurrentSettlement.Name);
          MBInformationManager.AddQuickInformation(message);
        }
        return itemNumber <= this._neededGrainAmount ? itemNumber : this._neededGrainAmount;
      }

      private void CheckIfPlayerReadyToReturnGrains()
      {
        if (this._playerHasNeededGrainsLog == null && this._playerAcceptedQuestLog.CurrentProgress >= this._neededGrainAmount)
        {
          this._playerHasNeededGrainsLog = this.AddLog(this._playerHasNeededGrainsLogText);
        }
        else
        {
          if (this._playerHasNeededGrainsLog == null || this._playerAcceptedQuestLog.CurrentProgress >= this._neededGrainAmount)
            return;
          this.RemoveLog(this._playerHasNeededGrainsLog);
          this._playerHasNeededGrainsLog = (JournalLog) null;
        }
      }

      private void OnPlayerInventoryExchange(
        List<(ItemRosterElement, int)> purchasedItems,
        List<(ItemRosterElement, int)> soldItems,
        bool isTrading)
      {
        bool flag = false;
        foreach ((ItemRosterElement, int) purchasedItem in purchasedItems)
        {
          if (purchasedItem.Item1.EquipmentElement.Item == DefaultItems.Grain)
          {
            flag = true;
            break;
          }
        }
        if (!flag)
        {
          foreach ((ItemRosterElement, int) soldItem in soldItems)
          {
            if (soldItem.Item1.EquipmentElement.Item == DefaultItems.Grain)
            {
              flag = true;
              break;
            }
          }
        }
        if (!flag)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnPartyConsumedFood(MobileParty party)
      {
        if (!party.IsMainParty)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnHeroSharedFoodWithAnotherHero(
        Hero supporterHero,
        Hero supportedHero,
        float influence)
      {
        if (supporterHero != Hero.MainHero && supportedHero != Hero.MainHero)
          return;
        this._playerAcceptedQuestLog.UpdateCurrentProgress(this.GetRequiredGrainCountOnPlayer());
        this.CheckIfPlayerReadyToReturnGrains();
      }

      private void OnClanChangedKingdom(
        Clan clan,
        Kingdom oldKingdom,
        Kingdom newKingdom,
        ChangeKingdomAction.ChangeKingdomActionDetail detail,
        bool showNotification = true)
      {
        if (!this.QuestGiver.CurrentSettlement.MapFaction.IsAtWarWith(Hero.MainHero.MapFaction))
          return;
        this.CompleteQuestWithCancel(this._cancelLogOnWarDeclared);
      }

      private void OnWarDeclared(
        IFaction faction1,
        IFaction faction2,
        DeclareWarAction.DeclareWarDetail detail)
      {
        if (detail == DeclareWarAction.DeclareWarDetail.CausedByCrimeRatingChange)
        {
          if (!this.QuestGiver.MapFaction.IsAtWarWith(Hero.MainHero.MapFaction))
            return;
          this.CriminalRatingFail();
        }
        else
          QuestHelper.CheckWarDeclarationAndFailOrCancelTheQuest((QuestBase) this, faction1, faction2, detail, this._playerDeclaredWarQuestLogText, this._cancelLogOnWarDeclared, true);
      }

      private void Success()
      {
        this.AddLog(this._successLog);
        TraitLevelingHelper.OnIssueSolvedThroughQuest(this.QuestGiver, new Tuple<TraitObject, int>[2]
        {
          new Tuple<TraitObject, int>(DefaultTraits.Mercy, 70),
          new Tuple<TraitObject, int>(DefaultTraits.Generosity, 50)
        });
        GiveGoldAction.ApplyBetweenCharacters((Hero) null, Hero.MainHero, this._rewardGold);
        ItemRosterElement itemRosterElement = new ItemRosterElement(DefaultItems.Grain, this._neededGrainAmount);
        GiveItemAction.ApplyForParties(PartyBase.MainParty, Settlement.CurrentSettlement.Party, in itemRosterElement);
        this.QuestGiver.AddPower(10f);
        this.QuestGiver.CurrentSettlement.Village.Bound.Town.Prosperity += 50f;
        this.RelationshipChangeWithQuestGiver = 2;
        foreach (Hero notable in (List<Hero>) this.QuestGiver.CurrentSettlement.Notables)
        {
          if (notable != this.QuestGiver)
            ChangeRelationAction.ApplyPlayerRelation(notable, 1);
        }
        this.CompleteQuestWithSuccess();
      }

      private void TimeoutFail()
      {
        this.QuestGiver.AddPower(-5f);
        this.QuestGiver.CurrentSettlement.Village.Bound.Town.Prosperity += -10f;
        this.RelationshipChangeWithQuestGiver = -5;
        foreach (Hero notable in (List<Hero>) this.QuestGiver.CurrentSettlement.Notables)
        {
          if (notable != this.QuestGiver)
            ChangeRelationAction.ApplyPlayerRelation(notable, -3);
        }
      }

      private void CriminalRatingFail()
      {
        this.QuestGiver.AddPower(-10f);
        this.RelationshipChangeWithQuestGiver = -5;
        TraitLevelingHelper.OnIssueFailed(Hero.MainHero, new Tuple<TraitObject, int>[1]
        {
          new Tuple<TraitObject, int>(DefaultTraits.Honor, -50)
        });
        this.CompleteQuestWithFail(this._failLogOnWarDeclaredByCriminalRating);
      }
    }

    public class HeadmanNeedsGrainIssueTypeDefiner : SaveableTypeDefiner
    {
      public HeadmanNeedsGrainIssueTypeDefiner()
        : base(440000)
      {
      }

      protected override void DefineClassTypes()
      {
        this.AddClassDefinition(typeof (HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssue), 1);
        this.AddClassDefinition(typeof (HeadmanNeedsGrainIssueBehavior.HeadmanNeedsGrainIssueQuest), 2);
      }
    }
  }
}
